#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>
#include <math.h>
#include "MQTTClient.h"
#include "cJSON.h"
#include "shmem.h"
#include "list.h"
#include <modbus.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/msg.h>
#include <errno.h>

#define ADDRESS "tcp://localhost:1883"
#define CLIENTID "GatewayReport"
#define TOPIC_UP "up"
#define TOPIC_DOWN "down"
#define QOS 1
#define TIMEOUT 10000L
#define CONFIG_PATH "/mnt/config/dianbiao.json"
#define DB_PATH "/mnt/data/history.db"

// 上报模式
typedef enum
{
    REPORT_NONE = 0,   // 不上报
    REPORT_CHANGE = 1, // 变化上报
    REPORT_TIMED = 2   // 周期上报
} ReportMode;

// 设备类型
typedef enum
{
    DEV_STM32 = 0,
    DEV_M0 = 1,
    DEV_MODBUS = 2,
    DEV_MBAPP = 3
} DeviceType;

// 全局配置结构
struct GlobalConfig
{
    int version;                // 协议版本
    ReportMode report_type;     // 上报类型
    int report_interval;        // 上报间隔(秒)
    char mqtt_addr[64];         // MQTT服务器地址
    int mqtt_port;              // MQTT端口
    char mb_dev_addr[64];       // modbus设备地址
    int mb_dev_port;            // modbus设备端口
    struct list_head data_list; // 数据点链表
    struct shm_param shm_para;  // 共享内存参数
    MQTTClient mqtt_client;     // MQTT客户端
    pthread_mutex_t lock;       // 线程锁
};

// // 数据点结构
// struct DataPoint {
//     int key;           // 唯一键值
//     char name[64];     // 数据点名称
//     int type;          // 数据类型(1:bool, 2:int, 3:float)
//     int dev_type;      // 设备类型
//     int addr;          // modbus地址 (仅modbus设备使用)
//     time_t timestamp;  // 最后更新时间
//     union {
//         int b_val;     // bool值
//         int i_val;     // int值
//         float f_val;   // float值
//     } old_val, new_val;
//   //  struct list_head list;  // 链表节点
// };

// 指令类型
typedef enum
{
    CMD_CONTROL,     // 控制命令
    CMD_REFRESH,     // 刷新上报
    CMD_CHANGE_MODE, // 修改上报模式
    CMD_HISTORY_DATA // 请求历史数据
} CommandType;

// 共享内存数据结构
typedef union val_t
{
    int b_val;   // bool类型存储空间
    int i_val;   // 整形值存储空间
    float f_val; // 浮点值存储空间
} val_t;

typedef struct std_node
{
    int key;       // 唯一键值
    int type;      // 数据点类型：1-bool, 2-int, 3-float
    int dev_type;  // 设备类型（例如：0-STM32, 1-Modbu）
    val_t old_val; // 旧值（用于变化检测）
    val_t new_val; // 新值（从设备采集的最新值）
    int ret;       // 采集状态：-1-失败，0-成功
} ShmDataNode;

// 函数声明
void *reporting_thread(void *arg);
void *storage_thread(void *arg);
void *command_thread(void *arg);

// 上报线程实现
void *reporting_thread(void *arg)
{
}

// 数据存储线程
void *storage_thread(void *arg)
{

    return NULL;
}

// 指令处理线程
void *command_thread(void *arg)
{

    return NULL;
}

int parse_config(struct GlobalConfig *config)
{
    FILE *fp = fopen(CONFIG_PATH, "r");
    if (!fp)
    {
        perror("Failed to open config file");

        return -1;
    }

    char buffer[4096]; // 增大缓冲区
    size_t len = fread(buffer, 1, sizeof(buffer) - 1, fp);
    buffer[len] = '\0';
    fclose(fp);

    cJSON *root = cJSON_Parse(buffer);
    if (!root)
    {
        fprintf(stderr, "JSON parse error: %s\n", cJSON_GetErrorPtr());
        return -1;
    }

    // 解析协议版本
    cJSON *version = cJSON_GetObjectItem(root, "version");
    if (version && version->valuestring)
    {
        if (strcmp(version->valuestring, "v1.0") == 0)
        {
            config->version = 1;
        }
    }

    // 解析上报配置
    cJSON *report = cJSON_GetObjectItem(root, "report");
    if (report)
    {
        cJSON *type = cJSON_GetObjectItem(report, "type");
        if (type)
        {
            config->report_type = (ReportMode)type->valueint;
        }
        cJSON *period = cJSON_GetObjectItem(report, "period");
        if (period)
        {
            config->report_interval = period->valueint;
        }
    }

    // 解析MQTT服务器配置
    cJSON *mqtt_server = cJSON_GetObjectItem(root, "mqtt_server");
    if (mqtt_server)
    {
        cJSON *addr = cJSON_GetObjectItem(mqtt_server, "addr");
        if (addr)
        {
            strncpy(config->mqtt_addr, addr->valuestring, sizeof(config->mqtt_addr) - 1);
        }
        cJSON *port = cJSON_GetObjectItem(mqtt_server, "port");
        if (port)
        {
            config->mqtt_port = port->valueint;
        }
    }

    // 解析modbus设备配置
    cJSON *mb_dev = cJSON_GetObjectItem(root, "mb_dev");
    if (mb_dev)
    {
        cJSON *addr = cJSON_GetObjectItem(mb_dev, "addr");
        if (addr)
        {
            strncpy(config->mb_dev_addr, addr->valuestring, sizeof(config->mb_dev_addr) - 1);
        }
        cJSON *port = cJSON_GetObjectItem(mb_dev, "port");
        if (port)
        {
            config->mb_dev_port = port->valueint;
        }

        printf("%s\n", addr->valuestring);
    }

    // 解析数据点 - stm32
    cJSON *stm32 = cJSON_GetObjectItem(root, "stm32");
    if (stm32)
    {
        cJSON *data = cJSON_GetObjectItem(stm32, "data");
        if (data)
        {
            int size = cJSON_GetArraySize(data);
            for (int i = 0; i < size; i++)
            {
                cJSON *item = cJSON_GetArrayItem(data, i);
                struct std_node *point = malloc(sizeof(struct std_node));
                memset(point, 0, sizeof(struct std_node));

                point->key = cJSON_GetObjectItem(item, "key")->valueint;

                point->type = cJSON_GetObjectItem(item, "type")->valueint;
                point->dev_type = 0; // stm32设备类型
                
              
                // 添加到链表
                // list_add_tail(&point->list, &config->data_list);
            }
        }
    }

    // 解析数据点 - modbus
    cJSON *modbus = cJSON_GetObjectItem(root, "modbus");
    if (modbus)
    {
        cJSON *data = cJSON_GetObjectItem(modbus, "data");
        if (data)
        {
            int size = cJSON_GetArraySize(data);
            for (int i = 0; i < size; i++)
            {
                cJSON *item = cJSON_GetArrayItem(data, i);
                struct std_node *point = malloc(sizeof(struct std_node));
                memset(point, 0, sizeof(struct std_node));

                point->key = cJSON_GetObjectItem(item, "key")->valueint;

                point->type = cJSON_GetObjectItem(item, "type")->valueint;
                // point->addr = cJSON_GetObjectItem(item, "addr")->valueint;
                point->dev_type = 2; // modbus设备类型

                // list_add_tail(&point->list, &config->data_list);
            }
        }
    }

    cJSON_Delete(root);
    return 0;
}

// 共享内存参数结构体
struct shm_param shm_para;
struct GlobalConfig *config;
int main(int argc, char const *argv[])
{
    FILE *fp;
    char buf[2048] = "";
    fp = fopen("/mnt/config/dianbiao.json", "r");
    if (fp == NULL)
    {
        perror("fopen err");
        return -1;
    }
    fread(buf, 2048, 1, fp);
    printf("%s\n", buf);

    int num_students = 6;
    // 初始化共享内存

    shm_init(&shm_para, "hello", 2048);
    void *addr = shm_getaddr(&shm_para);
    int *count_ptr = (int *)addr;
    *count_ptr = num_students;


    // 为全局配置分配内存
    config = (struct GlobalConfig *)malloc(sizeof(struct GlobalConfig));
    if (config == NULL)
    {
        perror("malloc for GlobalConfig failed");
        return -1;
    }

    // 初始化config结构体
    memset(config, 0, sizeof(struct GlobalConfig));
    INIT_LIST_HEAD(&config->data_list);      // 初始化链表头，需要确保list.h中提供了INIT_LIST_HEAD宏
    pthread_mutex_init(&config->lock, NULL); // 初始化锁

    // 解析json
    if (parse_config(config) != 0)
    {
        fprintf(stderr, "Parse config failed\n");
        free(config);
        return -1;
    }
    
    struct std_node *jiedian = (struct std_node *)(count_ptr + 1);
    
    strncpy(jiedian[0].key, "301", sizeof(jiedian[0].key) - 1);
    strncpy(jiedian[0].type, "", sizeof(jiedian[0].type) - 1);

  

    // 连接MQTT

    // 创建线程
    pthread_t report_tid, storage_tid, command_tid;
    // 上报线程
    if (pthread_create(&report_tid, NULL, reporting_thread, NULL) != 0)
    {
        perror("上报线程创建失败");
        return -1;
    }
    // 存储线程
    if (pthread_create(&storage_tid, NULL, storage_thread, NULL) != 0)
    {
        perror("存储线程创建失败");
        return -1;
    }
    // 指令处理线程
    if (pthread_create(&command_tid, NULL, command_thread, NULL) != 0)
    {
        perror("指令处理线程创建失败");
        return -1;
    }

    while (1)
    {
        /* code */
    }
    
    // 主线程等待
    pthread_join(report_tid, NULL);
    pthread_join(storage_tid, NULL);
    pthread_join(command_tid, NULL);

    return 0;
}
